# -*- coding: utf-8 -*-
from MediaCollection.Database import Database
from Exceptions.LibraryException import LibraryException

"""
Die Track-Klasse repräsentiert einen Track mit allen in der Datenbank 
gespeicherten Attributen. Über ein Objekt dieser Klasse können neue Einträge in 
die Datenbank eingefügt werden, im Gegenzug aber auch über die Id des Eintrags 
in der Datenbank die entsprechenden Informationen in das Objekt eingelesen 
werden.

@author: Philipp Dermitzel
@date: 2011-03-31
@version: 1.6.2
"""
class Track(object):
    
    """
    ----------------------------------------------------------------------------
    Konstruktor
    ----------------------------------------------------------------------------
    """
    
    """
    Der  Konstruktor. Erstellt das Objekt und liest, falls eine ID übergeben 
    wird, die entsprechenden Daten aus der Datenbank ein.
    @param id: Wird eine ID übergeben, so werden die Daten des entsprechenden 
        Tracks direkt eingelesen.
    @type id: int
    @param name: Wird ein Name, ein Artist und eine CD übergeben, so werden die 
        Daten des entsprechenden Tracks direkt eingelesen.
    @type name: String
    @param artist: Wird ein Name, ein Artist und eine CD übergeben, so werden 
        die Daten des entsprechenden Tracks direkt eingelesen.
    @type artist: int
    @param cd: Wird ein Name, ein Artist und eine CD übergeben, so werden die
        Daten des entsprechenden Tracks direkt eingelesen.
    @type cd: int
    @param path: Wird ein Pfad übergeben, so werden die Daten des entsprechenden
        Tracks direkt eingelesen.
    @type cd: String
    """
    def __init__(self, id = None, name = None, artist = None, cd = None, 
    path = None): 
        self.__trackData = {
            'id' : None,
            'name' : None,
            'artist' : None,
            'cd' : None,
            'trackOnCd' : None,
            'length' : None,
            'path' : None
        }
        
        if id is not None:
            self.__trackData['id'] = id
            self.getDataFromDb()
        elif (name is not None and artist is not None and cd is not None):
            self.__trackData['name'] = name
            self.__trackData['artist'] = artist
            self.__trackData['cd'] = cd
            self.getDataFromDb()
        elif path is not None:
            self.__trackData['path'] = path
            self.getDataFromDb()
    
    """
    ----------------------------------------------------------------------------
    Getter und Setter
    ----------------------------------------------------------------------------
    """
        
    """
    Setzt die Attribute des Tracks um dieses später erfolgreich in die Datenbank
    einfügen zu können. Dafür sollte das übergebene Dictionary C(dataDict) alle 
    eben dort beschriebenen Informationen enthalten.    
    @param dataDict: Alle benötigten Informationen zum Track. Die momentan 
    genutzten Felder sind: id, name, artist (DB-ID), cd (DB-ID), trackOnCD, 
    length, und path.
    @type dataDict: Dictionary
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Track
    """
    def setData(self, dataDict):
        if 'id' in dataDict:
            self.__trackData['id'] = dataDict['id']
        if 'name' in dataDict:
            self.__trackData['name'] = dataDict['name']
        if 'artist' in dataDict:
            self.__trackData['artist'] = dataDict['artist']
        if 'cd' in dataDict:
            self.__trackData['cd'] = dataDict['cd']
        if 'trackOnCd' in dataDict:
            self.__trackData['trackOnCd'] = dataDict['trackOnCd']
        if 'length' in dataDict:
            self.__trackData['length'] = dataDict['length']
        if 'path' in dataDict:
            self.__trackData['path'] = dataDict['path']
        return self
    
    """
    Setzt ein einzelnen Attribut des Tracks. Die momentan genutzten Felder sind:
    id, name, artist (DB-ID), cd (DB-ID), trackOnCD, length, und path.
    @param key: Der Schlüssel.
    @type key: String
    @param value: Der zu setzende Wert.
    @type value: int oder String
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Track
    """    
    def setValue(self, key, value):
        if key == "id":
            self.__trackData['id'] = value
        elif key == "name":
            self.__trackData['name'] = value
        elif key == "artist":
            self.__trackData['artist'] = value
        elif key == "cd":
            self.__trackData['cd'] = value
        elif key == "trackOnCd":
            self.__trackData['trackOnCd'] = value
        elif key == "length":
            self.__trackData['length'] = value
        elif key == "path":
            self.__trackData['path'] = value
        else: 
            raise LibraryException("\"%s\" ist kein valider Parameter" %key)
        return self
    
    """
    Getter
    @return: Alle Track-Daten.
    @rtype: Dictionary
    """    
    def getData(self):
        return self.__trackData
    
    """
    Getter.
    @return: Die ID des Tracks in der Datenbank.
    @rtype: int
    """
    def getId(self):
        return self.__trackData['id']
    
    """
    Getter.
    @return: Der Name des Tracks in der Datenbank.
    @rtype: String
    """
    def getName(self):
        return self.__trackData['name']
    
    """
    Getter.
    @return: Die ID des Artists in der Datenbank.
    @rtype: int
    """    
    def getArtist(self):
        return self.__trackData['artist']
    
    """
    Getter.
    @return: Die ID der CD in der Datenbank.
    @rtype: int
    """    
    def getCd(self):
        return self.__trackData['cd']
    
    """
    Getter.
    @return: Die Tracknummer auf der CD.
    @rtype: int
    """    
    def getTrackOnCd(self):
        return self.__trackData['trackOnCd']
    
    """
    Getter.
    @return: Die Länge des Tracks in Sekunden.
    @rtype: int
    """    
    def getLength(self):
        return self.__trackData['length']
    
    """
    Getter.
    @return: Der Pfad zur Datei.
    @rtype: String
    """    
    def getPath(self):
        return self.__trackData['path']
        
    """
    ----------------------------------------------------------------------------
    Methoden der Klasse
    ----------------------------------------------------------------------------
    """
    
    """
    Liest die Track-Daten aus der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Track
    """
    def getDataFromDb(self):
        if (self.__trackData['name'] is not None 
        and self.__trackData['artist'] is not None 
        and self.__trackData['cd'] is not None):
            arguments = { 
                'name'  : self.__trackData['name'],
                'artist': self.__trackData['artist'],
                'cd'    : self.__trackData['cd']
            }
        elif self.__trackData['id'] is not None:
            arguments = {'id':self.__trackData['id']}
        elif self.__trackData['path'] is not None:
            arguments = {'path':self.__trackData['path']}
        else: 
            raise LibraryException('Keine ID übergeben')
        
        db = Database()
        try: 
            db.select('*', 'Track', arguments)
            curTrack = db.dbCursor.fetchone()
            self.__trackData['id'] = curTrack[0]
            self.__trackData['name'] = curTrack[1]
            self.__trackData['artist'] = curTrack[2]
            self.__trackData['cd'] = curTrack[3]
            self.__trackData['trackOnCd'] = curTrack[4]
            self.__trackData['length'] = curTrack[5]
            self.__trackData['path'] = curTrack[6]
        except Exception:
            raise LibraryException('Track nicht vorhanden')
        return self
    
    """
    Speichert die Track-Daten in der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Track
    """   
    def insertIntoDb(self):
        if (self.__trackData['path'] is not None 
        and self.__trackData['length'] is not None):
            db = Database()
            db.savepoint("sp")
            try: 
                db.insert('Track', {
                    'name'      : self.__trackData['name'],
                    'artist'    : self.__trackData['artist'],
                    'cd'        : self.__trackData['cd'],
                    'trackOnCd' : self.__trackData['trackOnCd'],
                    'length'    : self.__trackData['length'],
                    'path'      : self.__trackData['path']
                })
                self.__trackData['id'] = db.dbCursor.lastrowid
                self.getDataFromDb()
            except Exception:
                db.rollback("sp")
                raise LibraryException('Konnte Daten nicht einfügen')
        else: 
            raise LibraryException('Nicht alle Daten vorhanden')
        return self
        
    """
    Löscht einen Track aus der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Track
    """    
    def deleteFromDb(self):
        if self.__trackData['id'] is None:
            self.getDataFromDb()
        db = Database()
        try: 
            db.delete('Track', {'id':self.__trackData['id']})
        except: raise LibraryException('Track nicht vorhanden')
        return self
